// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com

// ReSharper disable CheckNamespace
// ReSharper disable ClassNeverInstantiated.Global
// ReSharper disable CommentTypo
// ReSharper disable IdentifierTypo
// ReSharper disable InconsistentNaming
// ReSharper disable StringLiteralTypo
// ReSharper disable UnusedParameter.Local

/*
 * Ars Magna project, http://arsmagna.ru
 */

#region Using directives

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

#endregion

#nullable enable

namespace AM.Reporting.Utils
{
    /// <summary>
    /// The helper class used to create unique component names using the fastest method.
    /// </summary>
    /// <remarks>
    /// <para>Note: you can create unique component's name using its <b>CreateUniqueName</b> method.
    /// However, it is very slow and can't be used in some situations (when you create a report
    /// layout in a code and have a lot of objects on a page).</para>
    /// </remarks>
    /// <example>This example demonstrates how to use this class.
    /// <code>
    /// FastNameCreator nameCreator = new FastNameCreator(Report.AllObjects);
    /// foreach (Base c in Report.AllObjects)
    /// {
    ///   if (c.Name == "")
    ///     nameCreator.CreateUniqueName(c);
    /// }
    /// </code>
    /// </example>
    public class FastNameCreator
    {
        private readonly Hashtable baseNames;

        /// <summary>
        /// Creates the unique name for the given object.
        /// </summary>
        /// <param name="obj">The object to create name for.</param>
        public void CreateUniqueName (Base obj)
        {
            var baseName = obj.BaseName;
            var num = 1;
            if (baseNames.ContainsKey (baseName))
            {
                num = (int)baseNames[baseName] + 1;
            }

            obj.SetName (baseName + num.ToString());
            baseNames[baseName] = num;
        }

        /// <summary>
        /// Initializes a new instance of the <b>FastNameCreator</b> class with collection of
        /// existing report objects.
        /// </summary>
        /// <param name="objects">The collection of existing report objects.</param>
        public FastNameCreator (ObjectCollection objects)
        {
            baseNames = new Hashtable();

            foreach (Base obj in objects)
            {
                var objName = obj.Name;
                if (!string.IsNullOrEmpty (objName))
                {
                    // find numeric part
                    var i = objName.Length - 1;
                    while (i > 0 && objName[i] >= '0' && objName[i] <= '9')
                    {
                        i--;
                    }

                    if (i >= 0 && i < objName.Length - 1)
                    {
                        // get number
                        var baseName = objName.Substring (0, i + 1);
                        int.TryParse (objName.Substring (i + 1), out var num);
                        if (baseNames.ContainsKey (baseName))
                        {
                            var maxNum = (int)baseNames[baseName];
                            if (num < maxNum)
                            {
                                num = maxNum;
                            }
                        }

                        baseNames[baseName] = num;
                    }
                    else if (!baseNames.ContainsKey (objName))
                    {
                        baseNames[objName] = 0;
                    }
                }
            }
        }
    }
}
